<?php
class Container {
    protected $bindings = [];
    protected $instances = [];
    
    // 绑定接口到实现
    public function bind($abstract, $concrete = null, $shared = false) {
        if (is_null($concrete)) {
            $concrete = $abstract;
        }
        
        $this->bindings[$abstract] = [
            'concrete' => $concrete,
            'shared' => $shared
        ];
    }
    
    // 绑定单例
    public function singleton($abstract, $concrete = null) {
        $this->bind($abstract, $concrete, true);
    }
    
    // 解析依赖
    public function make($abstract) {
        // 如果已经有实例且是单例，直接返回
        if (isset($this->instances[$abstract])) {
            return $this->instances[$abstract];
        }
        
        // 获取具体实现
        $concrete = $this->getConcrete($abstract);
        
        // 创建实例
        $object = $this->build($concrete);
        
        // 如果是单例，保存实例
        if (isset($this->bindings[$abstract]) && $this->bindings[$abstract]['shared']) {
            $this->instances[$abstract] = $object;
        }
        
        return $object;
    }
    
    // 获取具体实现
    protected function getConcrete($abstract) {
        if (isset($this->bindings[$abstract])) {
            return $this->bindings[$abstract]['concrete'];
        }
        
        return $abstract;
    }
    
    // 构建实例
    protected function build($concrete) {
        // 如果是闭包，直接执行
        if ($concrete instanceof Closure) {
            return $concrete($this);
        }
        
        // 创建反射类
        $reflector = new ReflectionClass($concrete);
        
        // 检查类是否可实例化
        if (!$reflector->isInstantiable()) {
            throw new Exception("类 {$concrete} 不可实例化");
        }
        
        // 获取构造函数
        $constructor = $reflector->getConstructor();
        
        // 如果没有构造函数，直接创建实例
        if (is_null($constructor)) {
            return new $concrete;
        }
        
        // 获取构造函数参数
        $parameters = $constructor->getParameters();
        $dependencies = $this->resolveDependencies($parameters);
        
        // 创建实例并传入依赖
        return $reflector->newInstanceArgs($dependencies);
    }
    
    // 解析依赖参数
    protected function resolveDependencies($parameters) {
        $dependencies = [];
        
        foreach ($parameters as $parameter) {
            // 获取参数类型
            $dependency = $parameter->getClass();
            
            if (is_null($dependency)) {
                // 如果参数没有类型提示，检查是否有默认值
                if ($parameter->isDefaultValueAvailable()) {
                    $dependencies[] = $parameter->getDefaultValue();
                } else {
                    throw new Exception("无法解析参数 {$parameter->name}");
                }
            } else {
                // 递归解析依赖
                $dependencies[] = $this->make($dependency->name);
            }
        }
        
        return $dependencies;
    }
}
?>